package cn.com.chengmandian.core.web.service;

import cn.com.chengmandian.core.common.constants.CommonConstant;
import cn.com.chengmandian.core.web.exceptions.BadResponseException;
import cn.com.chengmandian.core.web.pojo.amap.BaseResponse;
import cn.com.chengmandian.core.web.pojo.amap.BicycleData;
import cn.com.chengmandian.core.web.pojo.amap.BicycleResponse;
import cn.com.chengmandian.core.web.pojo.amap.Direction;
import cn.com.chengmandian.core.web.pojo.amap.GeocodeRegeoResponse;
import cn.com.chengmandian.core.web.pojo.amap.RegeoCode;
import cn.com.chengmandian.core.web.pojo.amap.Route;
import cn.com.chengmandian.core.web.pojo.amap.WalkResponse;
import cn.com.chengmandian.core.web.pojo.txmap.Response;
import cn.com.chengmandian.core.web.properties.AmapProperties;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Map;
import java.util.TreeMap;

/**
 * 高德地图工具类
 */
@ConditionalOnProperty(prefix = "cmd.amap", name = "enable", havingValue = "true")
@Component
public class AmapService {

    private static final String SERVER_URL = "https://restapi.amap.com";
    private static final String GEOCODE_REGEO_URL = "/v3/geocode/regeo";
    private static final String DIRECTION_WALKING_URL = "/v3/direction/walking";
    private static final String DIRECTION_BICYCLING_URL = "/v4/direction/bicycling";

    @Autowired
    private AmapProperties amapProperties;

    public static void main(String[] args) throws Exception{
        AmapService service = new AmapService();
        BicycleData res = service.directionBicycling(BigDecimal.valueOf(116.481028), BigDecimal.valueOf(39.939643),BigDecimal.valueOf(116.483998), BigDecimal.valueOf(39.989943));
        System.out.print(JSONObject.toJSONString(res));
    }

    /**
     * 逆地理编码：将经纬度转换为详细结构化的地址，且返回附近周边的POI、AOI信息。
     * 例如：116.480881,39.989410 转换地址描述后：北京市朝阳区阜通东大街6号
     */
    public RegeoCode geocoder(BigDecimal lat, BigDecimal lng) {
        Map<String, String> param = new TreeMap<>();
        param.put("location", lng + "," + lat);
        String result = HttpUtil.get(getSigUrl(GEOCODE_REGEO_URL, param));
        GeocodeRegeoResponse response = JSONObject.parseObject(result, GeocodeRegeoResponse.class);
        if (response.getStatus().equals("0")) {
            throw new BadResponseException("AmapService error：" + response.getInfo());
        }
        return response.getRegeocode();
    }

    /**
     * 高德地图步行路径规划
     * 步行（walking）：基于步行路线规划。
     */
    public Route directionWalking(BigDecimal fromLng, BigDecimal fromLat, BigDecimal toLng, BigDecimal toLat) {
        Map<String, String> param = new TreeMap<>();
        param.put("origin", fromLng + "," + fromLat);
        param.put("destination", toLng + "," + toLat);
        String result = HttpUtil.get(getSigUrl(DIRECTION_WALKING_URL, param));
        WalkResponse<Route> response = JSONObject.parseObject(result, new TypeReference<WalkResponse<Route>>() {});
        if (!response.getStatus().equals(CommonConstant.ONE)) {
            throw new BadResponseException("AmapService error：" + response.getInfo());
        }
        return response.getRoute();
    }

    /**
     * 高德地图步行路径规划
     * 步行（bicycling）：基于自行车的骑行路线
     */
    public BicycleData directionBicycling(BigDecimal fromLng, BigDecimal fromLat, BigDecimal toLng, BigDecimal toLat) {
        Map<String, String> param = new TreeMap<>();
        param.put("origin", fromLng + "," + fromLat);
        param.put("destination", toLng + "," + toLat);
        String result = HttpUtil.get(getSigUrl(DIRECTION_BICYCLING_URL, param));
        BicycleResponse<BicycleData> response = JSONObject.parseObject(result, new TypeReference<BicycleResponse<BicycleData>>() {});
        if (!response.getErrCode().equals(CommonConstant.ZERO)) {
            throw new BadResponseException("AmapService error：" + response.getErrMsg());
        }
        return response.getData();
    }

    /**
     * 附加签名校验
     */
    private String getSigUrl(String url, Map<String, String> param) {
        param.put("key", amapProperties.getKey());
        url = url + "?" + MapUtil.join(param, "&", "=");
        return SERVER_URL + url;
    }
}
